###################################################################################################
# Analysis File ###################################################################################
# Restoration and Representation ##################################################################
# Michael Olson ###################################################################################
###################################################################################################

# working directory and packages ##################################################################

  multi_panel_table <- function(panels,
                                path,
                                dep_var_label = "",
                                note_width = 0.5,
                                item_list=NULL,
                                order=NULL,
                                table_placement="!ht",
                                table_caption,
                                table_font_size = "\\normalsize",
                                table_label,
                                p_level = 0.05,
                                note = ""){
    
    # panels is a list of lists, where each list has the following elements
    
    # fl_mods <- list(panel_title = "Florida",
    #                 models = list(fl_tt,fl_fe,fl_li),
    #                 var_names = c("Black Share $\\times$ Poll Tax",
    #                               "Poll Tax",
    #                               "Year",
    #                               "Year$^2$"),
    #                 omit = c("Year","Year$^2$"))
  
  if(!is.element("Hmisc",installed.packages())){install.packages("Hmisc")}
  require("Hmisc",quietly = T)

  if(!is.element("xtable",installed.packages())){install.packages("xtable")}
  require("xtable",quietly = T)
  
  detach("package:dplyr", unload=TRUE)
  if(!is.element("dplyr",installed.packages())){install.packages("dplyr")}
  require("dplyr",quietly = T)
  
  if(!is.element("rowr",installed.packages())){install.packages("rowr")}
  require("rowr",quietly = T)
  
  # define function

    cbind.fill.na <- function(...,fill=NA){cbind.fill(...,fill=NA)}
    
  # create the data frames for each model

  df_out <- list()
  
  for(q in 1:length(panels)){
  
    panel <- panels[[q]]
  
    coef_list <- list()
    sum_list  <- list()
    
    name_binder <- vector()
    
    for(j in 1:length(panel$models)){
      
      unit_name <- grep("numeric",grep("county",names(panel$models[[j]]$fe),value=T),invert=T,value=T)
      
      names <- rownames(panel$models[[j]]$coefficients)
      se_names <- paste(names,"se",sep="_")
      names <- c(rbind(names,se_names))
      
      name_binder <- c(name_binder,names[!is.element(names,name_binder)])
      
    }
    
    for(j in 1:length(panel$models)){
      
      unit_name <- names(panel$models[[j]]$clustervar)[1]
      
      names <- rownames(panel$models[[j]]$coefficients)
      se_names <- paste(names,"se",sep="_")
      names <- c(rbind(names,se_names))
      
      if(!is.null(unit_name)){
      coefs <- c(rbind(as.vector(panel$models[[j]]$coefficients),as.vector(panel$models[[j]]$cse)))
      }
      else{
      coefs <- c(rbind(as.vector(panel$models[[j]]$coefficients),as.vector(panel$models[[j]]$rse)))
      }
      
      coefs <- cbind(names,coefs)
      
        missing_coef_names <- coefs[coefs[,2]=="NaN",1]
        missing_se_names <- paste(missing_coef_names,"se",sep="_")
        
      coefs <- coefs[!is.element(coefs[,1],c(missing_coef_names,missing_se_names)),]
      
      sums <- c(panel$models[[j]]$N,length(unique(unlist(panel$models[[j]]$clustervar[unit_name]))))
      sum_names <- c("n","cl")
      
      sums <- cbind(sum_names,sums)
      
      coefs <- as.data.frame(rbind(coefs,sums))
      
      coef_list[[j]] <- coefs
      
    }
    
     names <- c(name_binder,"n","cl")
    
    for(j in 1:length(coef_list)){
      
      if(j == 1){
        
        bit <- left_join(as.data.frame(names),coef_list[[j]],by="names")
        
      } else{
        
        bit <- left_join(bit,coef_list[[j]],by="names")
        
      }
      
    }

  if(is.null(unit_name)){bit <- bit[bit$names!="cl",]}
    
  mod_df <- bit[,-which(colnames(bit)=="names")]
  mod_df <- as.data.frame(t(apply(mod_df,1,function(x) as.numeric(as.character(x)))))

  sub_off <- ifelse(is.null(unit_name),1,2)
  mod_df <- format.df(mod_df,rdec=c(rep(3,(nrow(mod_df)-sub_off)),rep(0,sub_off)),na.blank = T,dcolumn = T)
    
    # add significance stars
  
        p_holder <- list()
        for(j in 1:length(panels[[q]]$models)){p_holder[[j]] <- which(summary(panels[[q]]$models[[j]])$coefficients[,4]<p_level)}
      
        for(j in 1:ncol(mod_df)){
          
          col <- mod_df[,j]
          col[col!=""][1:length(col)%%2==1][p_holder[[j]]] <- paste(col[col!=""][1:length(col)%%2==1][p_holder[[j]]],"$^*$",sep="")
          mod_df[,j] <- col
          
        }
        
        
  mod_df[(1:(nrow(mod_df)-1))%%2==0,] <- paste0("(", format(unlist( mod_df[(1:(nrow(mod_df)-1))%%2==0,] )),")")
  
  mod_df <- gsub("()","",fixed=T,gsub("($$)","$$",fixed=T,gsub(" ","",fixed=T,mod_df)))
  
  mod_df <- as.data.frame(mod_df)
  
  mod_df$labels <- if(length(panel$var_names)>0 & !is.null(unit_name)){
                     c(c(rbind(panel$var_names,rep("",length(panel$var_names)))),"Observations","No. Clusters")
  } else if(length(panel$var_names)>0 & is.null(unit_name)){
    c(c(rbind(panel$var_names,rep("",length(panel$var_names)))),"Observations")
  } else{bit$names}
    
  omit_indices <- which(is.element(panel$var_names,panel$omit))
  omit_indices <- (2*omit_indices)-1
  omit_indices <- c(omit_indices,omit_indices+1)
  
  if(length(omit_indices)>0) mod_df <- mod_df[-omit_indices,]
  
  if(!is.null(order)){
    order_out <- list()
    for(j in 1:length(order)){order_out[[j]] <- c(2*order[j]-1,2*order[j])}
    order_new <- unlist(order_out)
    if(is.null(unit_name)){order_new <- c(order_new,nrow(mod_df))} else {order_new <- c(order_new,(nrow(mod_df)-1),nrow(mod_df))}
    
  mod_df <- mod_df[order_new,]  

  }
  
  df_out[[q]] <- mod_df

    }

  df_out <- lapply(df_out,as.data.frame)
  
  combine <- do.call(rbind,df_out)
  
  colnames(combine)[colnames(combine)!="labels"] <- paste(colnames(combine)[colnames(combine)!="labels"],1:length(colnames(combine)[colnames(combine)!="labels"] ),sep="_")
  
  combine <- combine %>%  select(labels, everything())  
  
  combine <- xtable::xtable(combine,
                              caption=table_caption,
                              label=table_label)

  ##### add rows ########
  
  num_cols <- max(unlist(lapply(panels,function(x) length(x$models))))
  num_rows <- nrow(do.call(rbind,df_out))
  panel_labels <- unlist(lapply(panels,function(x) x$panel_title))
  
  addtorow <- list()

    # define the positions to add lines
                     
    position <- c(0,0,0,0,0,0,0,0,0) # start with the header and the start of the first panel
    for(j in 1:(length(df_out)-1)){
      position <- c(position,rep(position[length(position)]+nrow(df_out[[j]]),3)) # add spots for each panel header
    }
    position <- c(position,rep(num_rows,2+length(item_list)))
        
  addtorow$pos <- as.list(position)
  
  # add rows content
  
    dep_var_label_table <- table(factor(dep_var_label,levels=unique(dep_var_label)))
    bit <- list()
    
    for(j in 1:length(dep_var_label_table)){
      
      bit[[j]] <- paste("\\multicolumn{",dep_var_label_table[j],"}{c}{",names(dep_var_label_table)[j],"}",sep="")
      
    }
    
     bit <- paste(unlist(bit),sep=" & ",collapse=" & ")
  
    if(length(dep_var_label)==1){
  
    addrows <- c( "\\hline \\\\\n  [-2.8ex] \\\\\n ",
                  paste("[-1.8ex]  &\\multicolumn{",num_cols,"}{c}{\\textit{Dependent Variable}} \\\\\n",sep=""),
                  paste("\\cline{2-",num_cols+1,"} \\\\\n",sep=""),
                  paste("[-1.8ex]  &\\multicolumn{",num_cols,"}{c}{",dep_var_label,"} \\\\\n",sep=""),
                  paste("\\cline{2-",num_cols+1,"} \\\\\n",sep=""),
                  paste("[-1.8ex] &",paste("(",seq(1,num_cols,1),")",sep="",collapse=" & "),"\\\\\n"))
    } else{
    
    addrows <- c( "\\hline \\\\\n  [-2.8ex] \\\\\n ",
                  paste("[-1.8ex]  &\\multicolumn{",num_cols,"}{c}{\\textit{Dependent Variable}} \\\\\n",sep=""),
                  paste("\\cline{2-",num_cols+1,"} \\\\\n",sep=""),
                  paste("[-1.8ex]  & ",bit, "\\\\\n",sep=""),
                  paste("\\cline{2-",num_cols+1,"} \\\\\n",sep=""),
                  paste("[-1.8ex] &",paste("(",seq(1,num_cols,1),")",sep="",collapse=" & "),"\\\\\n"))
    
    }
    
    for(j in 1:length(df_out)){
      
      addrows <- c(addrows,
                   "[0.5ex]  \\hline \\\\\n",
                   paste("[-1.8ex] \\textbf{Panel ",j,": ",panel_labels[j], "}  \\\\\n",sep=""),
                   "\\hline \\\\\n [-1ex]")
      
    }
  
  addrows <- c(addrows,"[1ex]  \\hline \\\\\n [-1.8ex]")
  
  if(length(item_list)>0){
  for(q in 1:length(item_list)){
    
    addrows <- c(addrows,ifelse(q==length(item_list),paste(paste(item_list[[q]],sep=" & ",collapse=" & ")," \\\\\n [0.5ex] \\hline \\\\\n [-1.8ex]"),
                                paste(paste(item_list[[q]],sep=" & ",collapse=" & ")," \\\\\n")))
    
  }
  }
  
  addrows <- c(addrows,
               paste("\\multicolumn{",num_cols+1,"}{l}{\\parbox[t]{",note_width,"\\textwidth}{",table_font_size," \\textit{Note}:",
                     note,"}}"))
  
  
  addtorow$command  <- addrows
  
  align(combine) <- c("l","l",rep("c",(ncol(df_out[[1]])-1)))
  
  print.xtable(combine,
               include.rownames = F,
               include.colnames = F,
               sanitize.text.function = function(x){x},
               booktabs = T,hline.after = NULL,
               table.placement = table_placement,
               add.to.row = addtorow,
               caption.placement = "top",
               size=table_font_size,
               file=path)

  }

